﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.SharePoint;
using Quix;
using System.IO;
using System.Xml;
using System.Xml.Linq;

namespace Quix
{
    class Program
    {
        static double dblVersionSizeLimit = 0, dblFileSizeLimit = 0, dblFolderSizeLimit = 0;
        static XElement eltRoot;
        [System.STAThreadAttribute()]
        [PreEmptive.Attributes.Setup(CustomEndpoint = "so-s.info/PreEmptive.Web.Services.Messaging/MessagingServiceV2.asmx")]
        [PreEmptive.Attributes.Teardown()]
        [PreEmptive.Attributes.Feature("AnalyzeLibrary")]
        static void Main(string[] args)
        {
            if (args.Count() == 0)
            {
                PrintUsage();
            }
            else
            {
                try
                {
                    System.Collections.Hashtable tbl = Core.HashArgs(args);
                    if (!tbl.ContainsKey("-url") || !tbl.ContainsKey("-library"))
                    {
                        PrintUsage();
                    }
                    else
                    {
                        StartProcessing();
                        //FileStream fs = new FileStream(".\\UAE_Patriot.xml", FileMode.Open);
                        //Core.SelfSanitizingStreamReader rdr = new Core.SelfSanitizingStreamReader(fs);
                        //var doc = XDocument.Parse(rdr.ReadToEnd());
                        //rdr.Close();
                        //rdr.Dispose();
                        //double dblFolder = 0, dblFile = 0, dblVersion = 0;
                        //foreach (XElement e in doc.Descendants("Folder"))
                        //{
                        //    try
                        //    {
                        //        dblFolder += Convert.ToDouble(e.Attribute("Size").Value);
                        //    }
                        //    catch { }
                        //}
                        //foreach (XElement e in doc.Descendants("File"))
                        //{
                        //    try
                        //    {
                        //        dblFile += Convert.ToDouble(e.Attribute("Size").Value);
                        //    }
                        //    catch { }
                        //}
                        //foreach (XElement e in doc.Descendants("Version"))
                        //{
                        //    try
                        //    {
                        //        dblVersion += Convert.ToDouble(e.Attribute("Size").Value);
                        //    }
                        //    catch { }
                        //}
                        if (tbl.ContainsKey("-versionsize"))
                        {
                            dblVersionSizeLimit = Convert.ToDouble(tbl["-versionsize"]);
                        }
                        if (tbl.ContainsKey("-filesize"))
                        {
                            dblFileSizeLimit = Convert.ToDouble(tbl["-filesize"]);
                        }
                        if (tbl.ContainsKey("-foldersize"))
                        {
                            dblFolderSizeLimit = Convert.ToDouble(tbl["-foldersize"]);
                        }
                        System.IO.StreamWriter sw = new System.IO.StreamWriter(Core.ConvertArgsToLogFile(tbl["-url"].ToString()));
                        using (SPSite sps = new SPSite(tbl["-url"].ToString()))
                        {
                            SPWeb spw = sps.OpenWeb();
                            SPFolder fld = spw.Folders[tbl["-library"].ToString()];
                            eltRoot = new XElement("Library");
                            Core.Log("Total Size: " + Math.Round(ProcessFolder(fld, sw, eltRoot, true) / 1024 /1024, 2).ToString() + " MB", sw, ConsoleColor.Red);
                            System.IO.StreamWriter swXml = new System.IO.StreamWriter("Flat-" + tbl["-output"].ToString());
                            Core.Log(eltRoot.ToString(), swXml);
                            swXml.Flush();
                            swXml.Close();
                            ProcessFolder(fld, sw, eltRoot, false);
                            swXml = new System.IO.StreamWriter(tbl["-output"].ToString());
                            Core.Log(eltRoot.ToString(), swXml);
                            swXml.Flush();
                            swXml.Close();
                            sw.Flush();
                        }
                        StopProcessing();
                    }
                }
                catch (Exception ex)
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine(ex.Message);
                }
            }
        }

        static double ProcessFolder(SPFolder fld, System.IO.StreamWriter sw, XElement elt, bool blnFlat)
        {
            double dblSize = 0, dblVersionSize = 0;
            XElement e;
            foreach (SPFolder fld2 in fld.SubFolders)
            {
                if (blnFlat)
                {
                    dblSize += ProcessFolder(fld2, sw, elt, blnFlat);
                }
                else
                {
                    XElement eltSubFolder = new XElement("Folder");
                    dblSize += ProcessFolder(fld2, sw, eltSubFolder, blnFlat);
                    elt.Add(eltSubFolder);
                }
            }
            foreach (SPFile fil in fld.Files)
            {
                if (fil.Length > dblFileSizeLimit)
                {
                    elt.Add(new XElement("File",
                            new XAttribute("Name", fil.Name),
                            new XAttribute("Size", Math.Round((Convert.ToDouble(fil.Length) / 1024 / 1024), 2).ToString()),
                            new XAttribute("Label", fil.UIVersionLabel)));
                    Core.Log("File [ " + fil.Name + " ] / Size: " + Math.Round((Convert.ToDouble(fil.Length) / 1024 / 1024), 2).ToString() + " MB", sw, ConsoleColor.White);
                }
                foreach (SPFileVersion ver in fil.Versions)
                {
                    dblVersionSize += ver.Size;
                }
                if (dblVersionSize > dblVersionSizeLimit)
                {
                    elt.Add(new XElement("Version", 
                            new XAttribute("Name", fil.Name),
                            new XAttribute("Size", Math.Round((dblVersionSize / 1024 / 1024), 2).ToString()),
                            new XAttribute("Label", fil.UIVersionLabel)));
                    Core.Log("Versions [ " + fil.Name + " ] / Size: " + Math.Round((dblVersionSize / 1024 / 1024), 2).ToString() + " MB / Version: " + fil.UIVersionLabel, sw, ConsoleColor.Gray);
                }
                dblSize += fil.Length;
                dblSize += dblVersionSize;
            }
            if (!blnFlat)
            {
                if (dblSize > dblFolderSizeLimit)
                {
                    elt.Add(new XAttribute("Name", fld.Name),
                            new XAttribute("Size", Math.Round((dblSize / 1024 / 1024), 2).ToString()));
                    Core.Log("Folder [ " + fld.Name + " ] / Size: " + Math.Round((dblSize / 1024 / 1024), 2).ToString() + " MB", sw, ConsoleColor.Yellow);
                }
            }
            return dblSize;
        }

        static void PrintUsage()
        {
            Console.ForegroundColor = ConsoleColor.White;
            Console.WriteLine(@"Command line error.\n\nUsage:\n  " + Environment.GetCommandLineArgs()[0] + " -url <URL> -library <Library> {-foldersize <FolderSizeInBytes>} {-filesize <FileSizeInBytes>} {-versionsize <VersionSizeInBytes>}");
            Console.WriteLine(@"    -url <URL> - URL of the target site e.g. http://www.crayveon.com/sites/Quix/Utilities");
            Console.WriteLine(@"    -library <Library> - Name of the target library e.g. Documents.");
            Console.WriteLine(@"    -output <Filename> - Name of the target xml file to write the output to e.g. Output.xml.");
            Console.WriteLine(@"    {Optional} -foldersize <FolderSizeInBytes> - Size of the folder content before inclusion in report e.g. 250000000 for 250 million bytes or just shy of 250 MB.");
            Console.WriteLine(@"    {Optional} -filesize <FileSizeInBytes> - Size of the file before inclusion in report e.g. 50000000 for 50 million bytes or just shy of 50 MB.");
            Console.WriteLine(@"    {Optional} -versionsize <VersionSizeInBytes> - Size of the accumulated version history before inclusion in report e.g. 100000000 for 100 million bytes or just shy of 100 MB.");
            Console.WriteLine(@"    Example usage would be:");
            Console.WriteLine(@"    " + Environment.GetCommandLineArgs()[0] + " -url http://crayveon.com/sites/Quix/Utilities -library Documents -output Output.xml -foldersize 250000000 -filesize 50000000 -versionsize 100000000");
        }

        [PreEmptive.Attributes.Feature("AnalyzeLibrary", EventType = PreEmptive.Attributes.FeatureEventTypes.Start)]
        static void StartProcessing()
        {
        }

        [PreEmptive.Attributes.Feature("AnalyzeLibrary", EventType = PreEmptive.Attributes.FeatureEventTypes.Stop)]
        static void StopProcessing()
        {
        }
    }
}
